(import (integer->float "System.Convert.ToDouble" (proc (integer) float)))
(define-imported-class (arraybasetype "System.Array") object)

(define ilist (type-expression-value 'ilist))
;; From Lists.scm
(import (empty? "Lists.IsEmpty" (proc (ilist) boolean))
	(rest "Lists.Rest" (proc (ilist) ilist))
	(cons "Lists.Cons" (proc (object ilist) ilist)))

(define-imported-class (random) object
  (define (random-integer "Next" (integer low) (integer high))
    (public) integer)
  (define (random-float "NextDouble")
    (public) float))

(define-module (lisp sequence-utils)
  (define-class sequence-utils object
    (define (as-object-array (object list)) (public static (array object))
      (let ((probe (as list (array object))))
	(if (null? probe)
	    (let ((il (cast ilist list)))
	      (let ((arr (new-array object (count il))))
		(copy-to il arr 0)
		arr))
	    probe)))

    (define (sublist (ilist sequence)
		     start sublist-length)
      (public static (array object))
      (let ((result (new-array object sublist-length))
	    (asarray (as sequence arraybasetype)))
	(cond ((null? asarray)
	       (dotimes (i sublist-length)
		 (set (vector-ref result i)
		      (vector-ref sequence (+ i start)))))
	      (else
	       (copy-subarray asarray start result 0 sublist-length)))
	result))

    (define (copy-sublist (ilist src) (integer spos)
			  (ilist dest) (integer dpos)
			  (integer len))
      (public static void)
      (dotimes (i len)
	(set (vector-ref dest dpos)
	     (vector-ref src spos))
	(set dpos (+ dpos 1))
	(set spos (+ spos 1))))

    (define (take (ilist sequence) n)
      (public static (array object))
      (sublist sequence 0 n))

    (define (drop (ilist sequence) n)
      (public static (array object))
      (sublist sequence
	       n
	       (- (count sequence)
		  n)))

    (define (take-right (ilist sequence) n)
      (public static (array object))
      (sublist sequence
	       (- (count sequence)
		  n)
	       n))

    (define (drop-right (ilist sequence) n)
      (public static (array object))
      (sublist sequence
	       0
	       (- (count sequence)
		  n)))

    (define (append2 (ilist seq1) (ilist seq2))
      (public static (array object))
      (let ((result (new-array object (+ (count seq1) (count seq2)))))
	(copy-into seq1 result 0)
	(copy-into seq2 result (count seq1))
	result))

    (define (index-of ilst ob) (public static integer)
      (%index-of (cast ilist ilst) ob))

    )

  (define-class utils object
    (define random-generator (public static random) (new random))

    (define (generic-= a b) (public static boolean)
      (cond ((is? a float)
	     (cond ((is? b float)
		    (eq? (cast float a)
			 (cast float b)))
		   ((is? b integer)
		    (eq? (cast float a)
			 (integer->float (cast integer b))))
		   (else
		    #f)))
	    ((is? a integer)
	     (cond ((is? b integer)
		    (eq? (cast integer a)
			 (cast integer b)))
		   ((is? b float)
		    (eq? (cast float b)
			 (integer->float (cast integer a))))
		   (else
		    #f)))
	    ((and (is? a character)
		  (is? b character))
	     (eq? (cast character a)
		  (cast character b)))
	    ((and (is? a boolean)
		  (is? b boolean))
	     (eq? (cast boolean a)
		  (cast boolean b)))
	    (else
	     (eq? a b))))))